/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Martin Karpisek (martin.karpisek@gmail.com) - bug 229474 *******************************************************************************/ package org.eclipse.ant.internal.ui.datatransfer; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.apache.tools.ant.Task; import org.apache.tools.ant.UnknownElement; import org.apache.tools.ant.taskdefs.Javac; import org.eclipse.ant.internal.core.IAntCoreConstants; import org.eclipse.ant.internal.ui.AntUIPlugin; import org.eclipse.ant.internal.ui.AntUtil; import org.eclipse.ant.internal.ui.model.AntModelContentProvider; import org.eclipse.ant.internal.ui.model.AntProjectNode; import org.eclipse.ant.internal.ui.model.AntTargetNode; import org.eclipse.ant.internal.ui.model.AntTaskNode; import org.eclipse.ant.internal.ui.model.IAntElement; import org.eclipse.ant.internal.ui.model.IAntModel; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.dialogs.IOverwriteQuery; import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider; import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider; import org.eclipse.ui.wizards.datatransfer.ImportOperation; public class AntNewJavaProjectPage extends WizardPage { private static class ImportOverwriteQuery implements IOverwriteQuery { @Override public String queryOverwrite(String file) { return ALL; } } private Text fProjectNameField; private Text fLocationPathField; private Button fBrowseButton; private Button fLinkButton; private IAntModel fAntModel; private ModifyListener fLocationModifyListener = new ModifyListener() { @Override public void modifyText(ModifyEvent e) { // no lexical or position, has task info fAntModel = AntUtil.getAntModel(getProjectLocationFieldValue(), false, false, true); AntProjectNode projectNode = fAntModel == null ? null : fAntModel.getProjectNode(); if (fAntModel != null && projectNode != null) { setProjectName(); // page will be validated on setting the project name List<AntTaskNode> javacNodes = new ArrayList<>(); getJavacNodes(javacNodes, projectNode); fTableViewer.setInput(javacNodes.toArray()); if (!javacNodes.isEmpty()) { fTableViewer.setSelection(new StructuredSelection(javacNodes.get(0))); } fTableViewer.getControl().setEnabled(true); } else { fTableViewer.setInput(new Object[] {}); fTableViewer.getControl().setEnabled(false); } setPageComplete(validatePage()); } }; private ModifyListener fNameModifyListener = new ModifyListener() { @Override public void modifyText(ModifyEvent e) { setPageComplete(validatePage()); } }; private static final int SIZING_TEXT_FIELD_WIDTH = 250; private TableViewer fTableViewer; public AntNewJavaProjectPage() { super("newPage"); //$NON-NLS-1$ setPageComplete(false); setTitle(DataTransferMessages.AntNewJavaProjectPage_9); setDescription(DataTransferMessages.AntNewJavaProjectPage_10); } /* * (non-Javadoc) * * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) */ @Override public void createControl(Composite parent) { initializeDialogUnits(parent); Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight = IDialogConstants.VERTICAL_MARGIN; layout.marginWidth = IDialogConstants.HORIZONTAL_MARGIN; layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); layout.numColumns = 3; composite.setLayout(layout); composite.setLayoutData(new GridData(GridData.FILL_BOTH)); composite.setFont(parent.getFont()); createProjectNameGroup(composite); createProjectLocationGroup(composite); createTargetsTable(composite); fLinkButton = new Button(composite, SWT.CHECK); fLinkButton.setText(DataTransferMessages.AntNewJavaProjectPage_24); fLinkButton.setFont(parent.getFont()); GridData gd = new GridData(); gd.horizontalAlignment = GridData.FILL; gd.grabExcessHorizontalSpace = false; gd.horizontalSpan = 2; fLinkButton.setLayoutData(gd); validatePage(); // Show description on opening setErrorMessage(null); setMessage(null); setControl(composite); } /** * Creates the project location specification controls. * * @param parent * the parent composite */ private final void createProjectLocationGroup(Composite parent) { // new project label Label projectContentsLabel = new Label(parent, SWT.NONE); projectContentsLabel.setText(DataTransferMessages.AntNewJavaProjectPage_11); projectContentsLabel.setFont(parent.getFont()); createUserSpecifiedProjectLocationGroup(parent); } /** * Creates the project name specification controls. * * @param parent * the parent composite */ private final void createProjectNameGroup(Composite parent) { Font dialogFont = parent.getFont(); // new project label Label projectLabel = new Label(parent, SWT.NONE); projectLabel.setText(DataTransferMessages.AntNewJavaProjectPage_12); projectLabel.setFont(dialogFont); GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); projectLabel.setLayoutData(gd); // new project name entry field fProjectNameField = new Text(parent, SWT.BORDER); gd = new GridData(); gd.horizontalAlignment = GridData.FILL; gd.grabExcessHorizontalSpace = false; gd.horizontalSpan = 2; fProjectNameField.setLayoutData(gd); fProjectNameField.setFont(dialogFont); fProjectNameField.addModifyListener(fNameModifyListener); } /** * Creates the project location specification controls. * * @param projectGroup * the parent composite */ private void createUserSpecifiedProjectLocationGroup(Composite projectGroup) { Font dialogFont = projectGroup.getFont(); // project location entry field fLocationPathField = new Text(projectGroup, SWT.BORDER); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.widthHint = SIZING_TEXT_FIELD_WIDTH; fLocationPathField.setLayoutData(data); fLocationPathField.setFont(dialogFont); // browse button fBrowseButton = new Button(projectGroup, SWT.PUSH); fBrowseButton.setText(DataTransferMessages.AntNewJavaProjectPage_13); fBrowseButton.setFont(dialogFont); setButtonLayoutData(fBrowseButton); fBrowseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { handleBrowseButtonPressed(); } }); fLocationPathField.addModifyListener(fLocationModifyListener); } /** * Returns the current project name * * @return the project name */ private String getProjectName(AntProjectNode projectNode) { String projectName = projectNode.getLabel(); if (projectName == null) { projectName = DataTransferMessages.AntNewJavaProjectPage_14; } return projectName; } /** * Returns the value of the project name field with leading and trailing spaces removed. * * @return the project name in the field */ private String getProjectNameFieldValue() { if (fProjectNameField == null) { return IAntCoreConstants.EMPTY_STRING; } return fProjectNameField.getText().trim(); } /** * Returns the value of the project location field with leading and trailing spaces removed. * * @return the project location directory in the field */ private String getProjectLocationFieldValue() { return fLocationPathField.getText().trim(); } /** * Determine the buildfile the user wishes to operate from */ private void handleBrowseButtonPressed() { String lastUsedPath = IAntCoreConstants.EMPTY_STRING; FileDialog dialog = new FileDialog(getShell(), SWT.SINGLE); dialog.setFilterExtensions(new String[] { "*.xml" }); //$NON-NLS-1$; dialog.setFilterPath(lastUsedPath); String result = dialog.open(); if (result == null) { return; } IPath filterPath = new Path(dialog.getFilterPath()); String buildFileName = dialog.getFileName(); IPath path = filterPath.append(buildFileName).makeAbsolute(); fLocationPathField.setText(path.toOSString()); } /** * Returns whether this page's controls currently all contain valid values. * * @return <code>true</code> if all controls are valid, and <code>false</code> if at least one is invalid */ private boolean validatePage() { String locationFieldContents = getProjectLocationFieldValue(); if (locationFieldContents.equals(IAntCoreConstants.EMPTY_STRING)) { setErrorMessage(null); setMessage(DataTransferMessages.AntNewJavaProjectPage_15); return false; } IPath path = new Path(IAntCoreConstants.EMPTY_STRING); if (!path.isValidPath(locationFieldContents)) { setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_16); return false; } if (fAntModel == null) { if (getBuildFile(locationFieldContents) == null) { setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_0); return false; } setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_17); return false; } if (fAntModel.getProjectNode() == null) { setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_2); return false; } if (getProjectNameFieldValue().length() == 0) { setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_18); return false; } try { IProject existingProject = ResourcesPlugin.getWorkspace().getRoot().getProject(getProjectNameFieldValue()); if (existingProject.exists()) { setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_19); return false; } } catch (IllegalArgumentException e) { setErrorMessage(NLS.bind(DataTransferMessages.AntNewJavaProjectPage_23, e.getLocalizedMessage())); return false; } if (fTableViewer.getTable().getItemCount() == 0) { setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_1); setPageComplete(false); return false; } setErrorMessage(null); setMessage(null); return true; } /** * Set the project name using either the name of the parent of the file or the name entry in the xml for the file */ private void setProjectName() { AntProjectNode node = fAntModel.getProjectNode(); String projectName = getProjectName(node); fProjectNameField.setText(projectName); } /** * Return a .xml file from the specified location. If there isn't one return null. */ private File getBuildFile(String locationFieldContents) { File buildFile = new File(locationFieldContents); if (!buildFile.isFile() || !buildFile.exists()) { return null; } return buildFile; } /** * Creates a new project resource based on the Ant buildfile. The classpath is configured based on the classpath of the javac declaration in the * buildfile. * * @return the created project resource, or <code>null</code> if the project was not created */ protected IJavaProject createProject() { final IJavaProject[] result = new IJavaProject[1]; final String projectName = getProjectNameFieldValue(); final File buildFile = getBuildFile(getProjectLocationFieldValue()); final List<?> selectedJavacs = ((IStructuredSelection) fTableViewer.getSelection()).toList(); final boolean link = fLinkButton.getSelection(); WorkspaceModifyOperation op = new WorkspaceModifyOperation() { @Override protected void execute(IProgressMonitor monitor) throws CoreException { List<?> javacTasks = resolveJavacTasks(selectedJavacs); ProjectCreator creator = new ProjectCreator(); Iterator<?> iter = javacTasks.iterator(); while (iter.hasNext()) { Javac javacTask = (Javac) iter.next(); IJavaProject javaProject = creator.createJavaProjectFromJavacNode(projectName, javacTask, monitor); importBuildFile(monitor, javaProject, buildFile, link); result[0] = javaProject; } } }; // run the new project creation operation try { getContainer().run(true, true, op); } catch (InterruptedException e) { return null; } catch (InvocationTargetException e) { // ie.- one of the steps resulted in a core exception Throwable t = e.getTargetException(); IStatus status = null; if (t instanceof CoreException) { status = ((CoreException) t).getStatus(); } else { status = new Status(IStatus.ERROR, AntUIPlugin.PI_ANTUI, IStatus.OK, "Error occurred. Check log for details ", t); //$NON-NLS-1$ AntUIPlugin.log(t); } ErrorDialog.openError(getShell(), DataTransferMessages.AntNewJavaProjectPage_21, null, status); } return result[0]; } protected void importBuildFile(IProgressMonitor monitor, IJavaProject javaProject, File buildFile, boolean link) { if (link) { IProject project = javaProject.getProject(); IFile iBuildFile = project.getFile(buildFile.getName()); if (!iBuildFile.exists()) { try { iBuildFile.createLink(new Path(buildFile.getAbsolutePath()), IResource.ALLOW_MISSING_LOCAL, monitor); } catch (CoreException e) { ErrorDialog.openError(getShell(), DataTransferMessages.AntNewJavaProjectPage_22, null, e.getStatus()); } } } else { IImportStructureProvider structureProvider = FileSystemStructureProvider.INSTANCE; File rootDir = buildFile.getParentFile(); try { ImportOperation op = new ImportOperation(javaProject.getPath(), rootDir, structureProvider, new ImportOverwriteQuery(), Collections.singletonList(buildFile)); op.setCreateContainerStructure(false); op.run(monitor); } catch (InterruptedException e) { // should not happen } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof CoreException) { ErrorDialog.openError(getShell(), DataTransferMessages.AntNewJavaProjectPage_22, null, ((CoreException) t).getStatus()); } } } } private List<?> resolveJavacTasks(List<?> javacNodes) { List<Object> resolvedJavacTasks = new ArrayList<>(javacNodes.size()); Iterator<?> nodes = javacNodes.iterator(); while (nodes.hasNext()) { AntTaskNode taskNode = (AntTaskNode) nodes.next(); Task javacTask = taskNode.getTask(); if (javacTask instanceof UnknownElement) { if (((UnknownElement) javacTask).getRealThing() == null) { javacTask.maybeConfigure(); } resolvedJavacTasks.add(((UnknownElement) javacTask).getRealThing()); } else { resolvedJavacTasks.add(javacTask); } } return resolvedJavacTasks; } private void getJavacNodes(List<AntTaskNode> javacNodes, IAntElement parent) { if (!parent.hasChildren()) { return; } List<IAntElement> children = parent.getChildNodes(); for (IAntElement node : children) { if (node instanceof AntTargetNode) { getJavacNodes(javacNodes, node); } else if (node instanceof AntTaskNode) { AntTaskNode task = (AntTaskNode) node; if ("javac".equals(task.getName())) { //$NON-NLS-1$ javacNodes.add(task); } } } } /* * (non-Javadoc) * * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean) */ @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { fLocationPathField.setFocus(); } } /** * Creates the table which displays the available targets * * @param parent * the parent composite */ private void createTargetsTable(Composite parent) { Font font = parent.getFont(); Label label = new Label(parent, SWT.NONE); label.setFont(font); label.setText(DataTransferMessages.AntNewJavaProjectPage_3); GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); gd.horizontalSpan = 3; label.setLayoutData(gd); Table table = new Table(parent, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION); GridData data = new GridData(GridData.FILL_BOTH); int availableRows = availableRows(parent); data.heightHint = table.getItemHeight() * (availableRows / 20); data.widthHint = 250; data.horizontalSpan = 3; table.setLayoutData(data); table.setFont(font); fTableViewer = new TableViewer(table); fTableViewer.setLabelProvider(new JavacTableLabelProvider()); fTableViewer.setContentProvider(new AntModelContentProvider()); fTableViewer.getControl().setEnabled(false); } /** * Return the number of rows available in the current display using the current font. * * @param parent * The Composite whose Font will be queried. * @return int The result of the display size divided by the font size. */ private int availableRows(Composite parent) { int fontHeight = (parent.getFont().getFontData())[0].getHeight(); int displayHeight = parent.getDisplay().getClientArea().height; return displayHeight / fontHeight; } }